Repository navigation
Add Conductor workspace automation - #44
Conversation
- Setup script handles dependency installation, direnv, and Neon branches - Each workspace gets isolated Neon database branch - Run script starts all dev servers via Turbo 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
WalkthroughAdds a new shell script and conductor config to automate Superset workspace setup: installs dependencies, symlinks Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant Conductor as conductor.json
participant Setup as conductor-setup.sh
participant Bun as bun
participant Neon as neonctl
participant JQ as jq
participant FS as Filesystem
User->>Conductor: invoke scripts.setup
Conductor->>Setup: execute ./conductor-setup.sh
activate Setup
Setup->>Bun: bun install
Bun-->>Setup: deps installed
Setup->>FS: symlink .envrc
FS-->>Setup: symlink created
Setup->>Neon: neonctl branch create (workspace)
Neon-->>Setup: JSON output
Setup->>JQ: parse DATABASE_URL / DATABASE_POOLED_URL
JQ-->>Setup: URL values
Setup->>FS: write .env
FS-->>Setup: .env created
Setup-->>User: completion message
deactivate Setup
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
conductor-setup.sh (1)
24-29: Handle emptyDATABASE_POOLED_URLmore explicitly.When
connection_uris[1]does not exist, the// emptyfilter produces an empty string, which is written to.envasDATABASE_POOLED_URL=(empty value). Downstream tooling may treat this differently than an unset variable or a commented-out line. Decide whether to:
- Omit the line entirely if the value is empty, or
- Keep the current behavior but document it, or
- Comment it out if empty.
Consider conditionally writing the line:
cat > .env << EOF DATABASE_URL=$DATABASE_URL +$(if [[ -n "$DATABASE_POOLED_URL" ]]; then echo "DATABASE_POOLED_URL=$DATABASE_POOLED_URL"; fi) EOFThis ensures
DATABASE_POOLED_URLis only present in.envif it has a non-empty value.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
conductor-setup.sh(1 hunks)conductor.json(1 hunks)
🔇 Additional comments (1)
conductor.json (1)
1-5: The second verification point from the review is now confirmed:conductor-setup.shis already marked executable (-rwxr-xr-xpermissions).However, the first verification point cannot be conclusively determined without clarifying which conductor framework is in use. The web search found multiple projects named "conductor" (Mac app, Netflix Conductor orchestration engine, etc.), each with different validation behaviors.
To complete verification of framework-level script validation, check your project's conductor documentation or
conductor.jsonschema to determine which framework is being used.
| #!/usr/bin/env bash | ||
| set -e | ||
|
|
||
| echo "🚀 Setting up Superset workspace..." | ||
|
|
||
| # Install dependencies | ||
| echo "📥 Installing dependencies..." | ||
| bun install | ||
|
|
||
| # Link direnv config | ||
| echo "🔧 Linking .envrc..." | ||
| ln -sf "$CONDUCTOR_ROOT_PATH/.envrc" .envrc | ||
|
|
||
| # Create Neon branch for this workspace | ||
| echo "🗄️ Creating Neon branch..." | ||
| WORKSPACE_NAME=$(basename "${CONDUCTOR_WORKSPACE_PATH:-$PWD}") | ||
| NEON_OUTPUT=$(neonctl branches create \ | ||
| --project-id tiny-cherry-82420694 \ | ||
| --name "$WORKSPACE_NAME" \ | ||
| --output json) | ||
|
|
||
| # Parse connection strings and create .env | ||
| DATABASE_URL=$(echo "$NEON_OUTPUT" | jq -r '.connection_uris[0].connection_uri') | ||
| DATABASE_POOLED_URL=$(echo "$NEON_OUTPUT" | jq -r '.connection_uris[1].connection_uri // empty') | ||
|
|
||
| cat > .env << EOF | ||
| DATABASE_URL=$DATABASE_URL | ||
| DATABASE_POOLED_URL=$DATABASE_POOLED_URL | ||
| EOF | ||
|
|
||
| echo "✨ Done! Neon branch: $WORKSPACE_NAME" |
There was a problem hiding this comment.
Add validation for required tools and better error handling.
The script assumes bun, neonctl, and jq are available in $PATH but does not validate this. If any tool is missing, the script will fail with a cryptic error from the missing command. Additionally, JSON parsing failures are not explicitly handled.
Apply this diff to add tool validation:
#!/usr/bin/env bash
set -e
+
+# Validate required tools
+for cmd in bun neonctl jq; do
+ if ! command -v "$cmd" &> /dev/null; then
+ echo "❌ Error: Required tool '$cmd' is not installed or not in \$PATH." >&2
+ exit 1
+ fi
+done
echo "🚀 Setting up Superset workspace..."Additionally, add validation after JSON parsing to ensure required fields are present:
# Parse connection strings and create .env
DATABASE_URL=$(echo "$NEON_OUTPUT" | jq -r '.connection_uris[0].connection_uri')
+if [[ -z "$DATABASE_URL" || "$DATABASE_URL" == "null" ]]; then
+ echo "❌ Error: Failed to extract DATABASE_URL from Neon response. Response was:" >&2
+ echo "$NEON_OUTPUT" >&2
+ exit 1
+fi
DATABASE_POOLED_URL=$(echo "$NEON_OUTPUT" | jq -r '.connection_uris[1].connection_uri // empty')📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| #!/usr/bin/env bash | |
| set -e | |
| echo "🚀 Setting up Superset workspace..." | |
| # Install dependencies | |
| echo "📥 Installing dependencies..." | |
| bun install | |
| # Link direnv config | |
| echo "🔧 Linking .envrc..." | |
| ln -sf "$CONDUCTOR_ROOT_PATH/.envrc" .envrc | |
| # Create Neon branch for this workspace | |
| echo "🗄️ Creating Neon branch..." | |
| WORKSPACE_NAME=$(basename "${CONDUCTOR_WORKSPACE_PATH:-$PWD}") | |
| NEON_OUTPUT=$(neonctl branches create \ | |
| --project-id tiny-cherry-82420694 \ | |
| --name "$WORKSPACE_NAME" \ | |
| --output json) | |
| # Parse connection strings and create .env | |
| DATABASE_URL=$(echo "$NEON_OUTPUT" | jq -r '.connection_uris[0].connection_uri') | |
| DATABASE_POOLED_URL=$(echo "$NEON_OUTPUT" | jq -r '.connection_uris[1].connection_uri // empty') | |
| cat > .env << EOF | |
| DATABASE_URL=$DATABASE_URL | |
| DATABASE_POOLED_URL=$DATABASE_POOLED_URL | |
| EOF | |
| echo "✨ Done! Neon branch: $WORKSPACE_NAME" | |
| #!/usr/bin/env bash | |
| set -e | |
| # Validate required tools | |
| for cmd in bun neonctl jq; do | |
| if ! command -v "$cmd" &> /dev/null; then | |
| echo "❌ Error: Required tool '$cmd' is not installed or not in \$PATH." >&2 | |
| exit 1 | |
| fi | |
| done | |
| echo "🚀 Setting up Superset workspace..." | |
| # Install dependencies | |
| echo "📥 Installing dependencies..." | |
| bun install | |
| # Link direnv config | |
| echo "🔧 Linking .envrc..." | |
| ln -sf "$CONDUCTOR_ROOT_PATH/.envrc" .envrc | |
| # Create Neon branch for this workspace | |
| echo "🗄️ Creating Neon branch..." | |
| WORKSPACE_NAME=$(basename "${CONDUCTOR_WORKSPACE_PATH:-$PWD}") | |
| NEON_OUTPUT=$(neonctl branches create \ | |
| --project-id tiny-cherry-82420694 \ | |
| --name "$WORKSPACE_NAME" \ | |
| --output json) | |
| # Parse connection strings and create .env | |
| DATABASE_URL=$(echo "$NEON_OUTPUT" | jq -r '.connection_uris[0].connection_uri') | |
| if [[ -z "$DATABASE_URL" || "$DATABASE_URL" == "null" ]]; then | |
| echo "❌ Error: Failed to extract DATABASE_URL from Neon response. Response was:" >&2 | |
| echo "$NEON_OUTPUT" >&2 | |
| exit 1 | |
| fi | |
| DATABASE_POOLED_URL=$(echo "$NEON_OUTPUT" | jq -r '.connection_uris[1].connection_uri // empty') | |
| cat > .env << EOF | |
| DATABASE_URL=$DATABASE_URL | |
| DATABASE_POOLED_URL=$DATABASE_POOLED_URL | |
| EOF | |
| echo "✨ Done! Neon branch: $WORKSPACE_NAME" |
🤖 Prompt for AI Agents
In conductor-setup.sh around lines 1 to 31, add upfront validation and clearer
error handling: check that bun, neonctl, and jq are present (use command -v and
exit with a clear message if any are missing); capture neonctl command failure
(check its exit status and/or capture stderr) and print a descriptive error
before exiting instead of letting the script fail silently; validate the JSON
output from neonctl with jq and verify the DATABASE_URL and, if required,
DATABASE_POOLED_URL are non-empty (exit with a clear error if parsing failed or
required fields are missing); only write the .env file after those validations
succeed and surface useful error messages for each failure case.
| WORKSPACE_NAME=$(basename "${CONDUCTOR_WORKSPACE_PATH:-$PWD}") | ||
| NEON_OUTPUT=$(neonctl branches create \ | ||
| --project-id tiny-cherry-82420694 \ | ||
| --name "$WORKSPACE_NAME" \ | ||
| --output json) |
There was a problem hiding this comment.
Script is not idempotent; rerunning will attempt duplicate Neon branch creation.
Neon will reject a second branches create call with the same --name. Running this setup script twice in the same workspace will fail. Consider:
- Checking if the branch already exists before attempting creation, or
- Documenting that the script should only run once per workspace, or
- Providing a separate idempotent "refresh" command if re-initialization is needed.
This could be addressed with a check before branch creation:
WORKSPACE_NAME=$(basename "${CONDUCTOR_WORKSPACE_PATH:-$PWD}")
+
+# Check if branch already exists
+if neonctl branches get "$WORKSPACE_NAME" --project-id "${NEON_PROJECT_ID}" &> /dev/null; then
+ echo "ℹ️ Neon branch already exists: $WORKSPACE_NAME"
+ NEON_OUTPUT=$(neonctl branches get "$WORKSPACE_NAME" --project-id "${NEON_PROJECT_ID}" --output json)
+else
+ echo "Creating new Neon branch..."
NEON_OUTPUT=$(neonctl branches create \
- --project-id tiny-cherry-82420694 \
+ --project-id "${NEON_PROJECT_ID:?Error: NEON_PROJECT_ID not set}" \
--name "$WORKSPACE_NAME" \
--output json)
+fiVerify that neonctl branches get and neonctl branches create outputs are compatible with the downstream JSON parsing.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| WORKSPACE_NAME=$(basename "${CONDUCTOR_WORKSPACE_PATH:-$PWD}") | |
| NEON_OUTPUT=$(neonctl branches create \ | |
| --project-id tiny-cherry-82420694 \ | |
| --name "$WORKSPACE_NAME" \ | |
| --output json) | |
| WORKSPACE_NAME=$(basename "${CONDUCTOR_WORKSPACE_PATH:-$PWD}") | |
| # Check if branch already exists | |
| if neonctl branches get "$WORKSPACE_NAME" --project-id "${NEON_PROJECT_ID}" &> /dev/null; then | |
| echo "ℹ️ Neon branch already exists: $WORKSPACE_NAME" | |
| NEON_OUTPUT=$(neonctl branches get "$WORKSPACE_NAME" --project-id "${NEON_PROJECT_ID}" --output json) | |
| else | |
| echo "Creating new Neon branch..." | |
| NEON_OUTPUT=$(neonctl branches create \ | |
| --project-id "${NEON_PROJECT_ID:?Error: NEON_PROJECT_ID not set}" \ | |
| --name "$WORKSPACE_NAME" \ | |
| --output json) | |
| fi |
🤖 Prompt for AI Agents
In conductor-setup.sh around lines 16 to 20, the script always calls `neonctl
branches create` which is not idempotent and will fail on reruns; change it to
first check for an existing branch by name (e.g., use `neonctl branches get` or
`neonctl branches list`/filter) and reuse the existing branch output if found,
otherwise call `neonctl branches create`; ensure you handle and parse both `get`
and `create` JSON outputs consistently (extract the branch identifier/URL the
rest of the script expects) and surface any errors clearly so the script can be
safely re-run.
| --project-id tiny-cherry-82420694 \ | ||
| --name "$WORKSPACE_NAME" \ | ||
| --output json) |
There was a problem hiding this comment.
Remove hardcoded project-id from the script.
Embedding tiny-cherry-82420694 as a hardcoded string violates configuration management best practices and creates a security risk by exposing project identifiers in version control. This should be sourced from an environment variable or configuration file instead.
Apply this diff to externalize the project-id:
WORKSPACE_NAME=$(basename "${CONDUCTOR_WORKSPACE_PATH:-$PWD}")
-NEON_OUTPUT=$(neonctl branches create \
- --project-id tiny-cherry-82420694 \
+NEON_OUTPUT=$(neonctl branches create \
+ --project-id "${NEON_PROJECT_ID:?Error: NEON_PROJECT_ID not set}" \
--name "$WORKSPACE_NAME" \
--output json)Ensure NEON_PROJECT_ID is set via environment variable, .env, or passed by the conductor framework before invoking this script.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| --project-id tiny-cherry-82420694 \ | |
| --name "$WORKSPACE_NAME" \ | |
| --output json) | |
| --project-id "${NEON_PROJECT_ID:?Error: NEON_PROJECT_ID not set}" \ | |
| --name "$WORKSPACE_NAME" \ | |
| --output json) |
🤖 Prompt for AI Agents
In conductor-setup.sh around lines 18 to 20, the script currently hardcodes the
project-id "tiny-cherry-82420694"; replace that literal with an
environment-driven value (e.g., use $NEON_PROJECT_ID), ensure the script
validates that NEON_PROJECT_ID is set (exit with a clear error if missing), and
document or load it from .env or the calling environment so the project id is
not embedded in source control.
| DATABASE_URL=$(echo "$NEON_OUTPUT" | jq -r '.connection_uris[0].connection_uri') | ||
| DATABASE_POOLED_URL=$(echo "$NEON_OUTPUT" | jq -r '.connection_uris[1].connection_uri // empty') |
There was a problem hiding this comment.
Fragile JSON parsing; assume specific Neon API response structure without graceful degradation.
The jq filters assume connection_uris[0] and connection_uris[1] always exist. If the Neon API response structure differs (e.g., fewer URIs, different keys, or schema changes), parsing will silently fail or produce null. The // empty fallback for DATABASE_POOLED_URL is good, but DATABASE_URL has no fallback and will be set to "null" string if missing, which will corrupt the .env file.
Strengthen the parsing logic and add validation (see previous comment for a full fix). Additionally, verify the jq output:
# Debug: Print the Neon output structure before parsing
echo "$NEON_OUTPUT" | jq '.'Confirm that .connection_uris[0].connection_uri and .connection_uris[1].connection_uri are the correct paths in all cases.
🤖 Prompt for AI Agents
In conductor-setup.sh around lines 23 to 24, the jq parsing assumes
connection_uris[0] always exists and will write the string "null" into the .env
if missing; change the parsing to (1) print/debug the raw NEON_OUTPUT (echo
"$NEON_OUTPUT" | jq '.') before extraction, (2) use jq with safe fallbacks for
DATABASE_URL and DATABASE_POOLED_URL (e.g. fall back to empty string or
alternate keys) so neither becomes the literal "null", (3) validate after
extraction that DATABASE_URL is non-empty and exit with a clear error if it is
missing, and (4) add a brief comment verifying the expected JSON paths and
handling alternate shapes so the script degrades gracefully when URIs are
absent.
| cat > .env << EOF | ||
| DATABASE_URL=$DATABASE_URL | ||
| DATABASE_POOLED_URL=$DATABASE_POOLED_URL | ||
| EOF |
There was a problem hiding this comment.
.env file is overwritten without warning, backup, or existence check.
If a user has manually edited or created a .env file with custom values, running this script will silently overwrite it. Consider:
- Checking if
.envalready exists and prompting the user, or - Creating a backup before overwriting, or
- Generating a workspace-specific
.env.conductorand sourcing it if needed.
Apply this diff to add a safety check:
-cat > .env << EOF
+if [[ -f .env ]]; then
+ echo "⚠️ Warning: .env already exists. Backing up to .env.bak"
+ mv .env .env.bak
+fi
+
+cat > .env << EOF
DATABASE_URL=$DATABASE_URL
DATABASE_POOLED_URL=$DATABASE_POOLED_URL
EOF📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| cat > .env << EOF | |
| DATABASE_URL=$DATABASE_URL | |
| DATABASE_POOLED_URL=$DATABASE_POOLED_URL | |
| EOF | |
| if [[ -f .env ]]; then | |
| echo "⚠️ Warning: .env already exists. Backing up to .env.bak" | |
| mv .env .env.bak | |
| fi | |
| cat > .env << EOF | |
| DATABASE_URL=$DATABASE_URL | |
| DATABASE_POOLED_URL=$DATABASE_POOLED_URL | |
| EOF |
🤖 Prompt for AI Agents
In conductor-setup.sh around lines 26 to 29, the script blindly writes a .env
file which can overwrite a user's existing file; modify the script to first
check for an existing .env and if found either prompt the user to confirm
overwrite, create a timestamped backup (e.g., .env.bak.YYYYMMDD_HHMMSS), or
write to a workspace-specific file like .env.conductor and optionally source it;
implement one of these flows and ensure the script communicates the action to
the user (prompt/backup created/alternate file written) before proceeding.
* Add Conductor workspace automation - Setup script handles dependency installation, direnv, and Neon branches - Each workspace gets isolated Neon database branch - Run script starts all dev servers via Turbo 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Remove run script - let developers choose which apps to run * Add dependency checks with clear error messages --------- Co-authored-by: Claude <noreply@anthropic.com>
Summary
Adds Conductor configuration for automated workspace setup:
How it works
Each workspace gets:
lisbon,paris).envwith connection strings.envrcfor direnv auto-loadingTest plan
lisbonworkspace.envgeneration with DATABASE_URL.envrcsymlink for direnv🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Chores